#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Filename: 01_analytical_solution.py
# 解析解(Analytical solution)的方式求解 θ(W)，这种方式是直接通过数学的方式计算出θ,
#   数据量小的话这种方式还能胜任, 一旦数据量偏大这种方式的时间成本会非常大

import matplotlib.pyplot as plt
import numpy as np

# 这里相当于是随机X维度X1，rand是随机均匀分布
# 我们一般认为x_0恒为1, 所以创建一个使用1填充的100行1列的向量
X_0 = np.ones((100, 1))
# np.random.rand(100, 1): 创建一个100行1列的向量, 每个数字都是在区间[0, 1)内
X_1 = 2 * np.random.rand(100, 1)

# y是人为的设置真实Y的一列
# 4 + 3 * X 是 y^, 4和3组成模型Model， 4是w0, 3是w1， x0恒为1，x1是X
# np.random.randn(100, 1)是伪造的误差error, 意思是返回一个100行1列的使用标准正太分布的值填充的向量
# randn是`标准正太分布`(μ=0,σ=1)
# 即： y = (y^) + error
y = (4 + 3 * X_1) + np.random.randn(100, 1)

# 整合X0和X1, 把一个100*1的1和一个100*1的随机数整合为100*2的矩阵
# c_：两个向量进行横向拼接
X = np.c_[X_0, X_1]
print("X=")
print(X)

# 常规等式求解theta
# linalg: Core Linear Algebra Tools：核心线性代数工具
# inv：求逆
# T:转置
# dot：点乘，点积
theta_best = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(y)

# 得到两个值，第一个就是w0，第二个就是w1, 可以发现这个值并不是我们预设的4和3，但是非常接近
print("theta_best:")
print(theta_best)

# 创建测试集
X0_test = np.ones((2, 1))
X1_test = np.array([[0], [2]])
X_test = np.c_[X0_test, X1_test]
print("X_test:")
print(X_test)

# 测试
y_predict = X_test.dot(theta_best)
print("y_predict:")
print(y_predict)

# 数据可视化
# 绘制预测图；第三个参数代表：红色`-`图
plt.plot(X1_test, y_predict, 'r-')

# 绘制真实数据分布；第三个参数代表：蓝色的`.`图
plt.plot(X_1, y, 'b.')

# 绘制坐标轴，x坐标范围 0~2，y坐标范围 0~15
plt.axis([0, 2, 0, 15])

# 显示绘制
plt.show()
